﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AMStudio.Driver.Omron;
using System.Text.RegularExpressions;

namespace AMStudio.Driver
{
    public class OmronFins : FinsTCP
    {
        private Regex AddressRegex = new Regex(
            @"^\s*(?<RegType>(CIO|[ATHCWED]))(?<StartAddress>\d{1,5})(.(?<BitIndex>([0-1][0-9]|1[0-5]|\d{1})))?\s*$");
        public OmronFins(FinsConfigData cfgData, IChannel client)
            : base(cfgData, client)
        {
        }
        public void Read(PLCPortsTag tag)
        {
            if (!base.ReadPacket(tag.RegType, tag.StartAddr, tag.ByteData))
            {
                throw new Exception("Read PLC Error" + tag.RegType + tag.StartAddr.ToString() + "." + tag.Index.ToString());
            }
        }
        public void Write(PLCPortsTag tag)
        {
            if (!base.WriteTag(tag.RegType, tag.StartAddr, tag.Index, tag.IsBitType, tag.ByteData))
            {
                throw new Exception("Write PLC Error" + tag.RegType + tag.StartAddr.ToString() + "." + tag.Index.ToString());
            }
        }
        public void Write(string tag, int length, object value)
        {
            bool result = false;
            Match m = AddressRegex.Match(tag);
            byte[] ByteValue;
            bool isBitType;
            string RegType = string.Empty;
            int StartAddress = 0;
            int BitIndex = 0;
            if (m.Success)
            {
                isBitType = false;
                RegType = m.Groups["RegType"].Value;
                StartAddress = int.Parse(m.Groups["StartAddress"].Value);
                BitIndex = 0;
                if (m.Groups["BitIndex"].Length > 0)
                {
                    BitIndex = int.Parse(m.Groups["BitIndex"].Value);
                    isBitType = true;
                    ByteValue = new byte[2];
                    ByteValue[0] = (byte)value;
                }
                else
                {
                    if (length == 1)
                    {
                        int v = (int)value;
                        ByteValue = new byte[2 * length];
                        for (int i = 0; i < length; i++)
                        {
                            ByteValue[2 * i] = (byte)(v >> 8);
                            ByteValue[2 * i + 1] = (byte)(v & 0xffL);
                        }
                    }
                    else
                    {
                        int[] v = value as int[];
                        ByteValue = new byte[2 * length];
                        for (int i = 0; i < length; i++)
                        {
                            ByteValue[2 * i] = (byte)(v[i] >> 8);
                            ByteValue[2 * i + 1] = (byte)(v[i] & 0xffL);
                        }
                    }
                }
                result = base.WriteTag(RegType, StartAddress, BitIndex, isBitType, ByteValue);
            }
            else
            {
                throw new Exception("Wrong PLC Write Address" + StartAddress.ToString() + "." + BitIndex.ToString());
            }
            if (!result)
            {
                throw new Exception("Write PLC Error" + StartAddress.ToString() + "." + BitIndex.ToString());
            }
        }
        public void Write(string tag, int length, string value)
        {
            bool result = false;
            Match m = AddressRegex.Match(tag);
            byte[] ByteValue;
            bool isBitType;
            string RegType = string.Empty;
            int StartAddress = 0;
            int BitIndex = 0;
            if (m.Success)
            {
                isBitType = false;
                RegType = m.Groups["RegType"].Value;
                StartAddress = int.Parse(m.Groups["StartAddress"].Value);
                BitIndex = 0;
                if (m.Groups["BitIndex"].Length > 0)
                {
                    BitIndex = int.Parse(m.Groups["BitIndex"].Value);
                    isBitType = true;
                    ByteValue = new byte[0];
                    ByteValue[0] = byte.Parse(value);
                }
                else
                {
                    if (length == 1)
                    {
                        int v = int.Parse(value);
                        ByteValue = new byte[2 * length];
                        for (int i = 0; i < length; i++)
                        {
                            ByteValue[2 * i] = (byte)(v >> 8);
                            ByteValue[2 * i + 1] = (byte)(v & 0xffL);
                        }
                    }
                    else
                    {
                        int[] v = new int[length];
                        string[] r = value.Split(',');
                        for (int i = 0; i < v.Length; i++)
                        {
                            v[i] = int.Parse(r[i]);
                        }
                        ByteValue = new byte[2 * length];
                        for (int i = 0; i < length; i++)
                        {
                            ByteValue[2 * i] = (byte)(v[i] >> 8);
                            ByteValue[2 * i + 1] = (byte)(v[i] & 0xffL);
                        }
                    }
                }
                result = base.WriteTag(RegType, StartAddress, BitIndex, isBitType, ByteValue);
            }
            else
            {
                throw new Exception("Wrong PLC Write Address" + StartAddress.ToString() + "." + BitIndex.ToString());
            }
            if (!result)
            {
                throw new Exception("Write PLC Error" + StartAddress.ToString() + "." + BitIndex.ToString());
            }
        }
        public object Read(string tag, int length)
        {
            Match m = AddressRegex.Match(tag);
            byte[] ByteValue;
            string RegType = string.Empty;
            int StartAddress = 0;
            int BitIndex = 0;
            if (m.Success)
            {
                RegType = m.Groups["RegType"].Value;
                StartAddress = int.Parse(m.Groups["StartAddress"].Value);
                BitIndex = 0;
                if (m.Groups["BitIndex"].Length > 0)
                {
                    BitIndex = int.Parse(m.Groups["BitIndex"].Value);
                    ByteValue = new byte[2];
                    if (!base.ReadPacket(RegType, StartAddress, ByteValue))
                    {
                        throw new Exception("Read PLC Error" + StartAddress + "." + BitIndex);
                    }
                    int intRes = 0;
                    for (int i = 0; i < length; i++)
                    {
                        intRes += ((int)ByteValue[2 * i]) << 8;
                        intRes += ByteValue[2 * i + 1];
                    }
                    return GetBitValue(intRes, BitIndex);
                }
                else
                {
                    if (length == 1)
                    {
                        ByteValue = new byte[2];
                        if (!base.ReadPacket(RegType, StartAddress, ByteValue))
                        {
                            throw new Exception("Read PLC Error" + StartAddress + "." + BitIndex);
                        }
                        int intRes = 0;
                        for (int i = 0; i < length; i++)
                        {
                            intRes += ((int)ByteValue[2 * i]) << 8;
                            intRes += ByteValue[2 * i + 1];
                        }
                        return intRes;
                    }
                    else
                    {
                        int[] v = new int[length];
                        ByteValue = new byte[2 * length];
                        if (!base.ReadPacket(RegType, StartAddress, ByteValue))
                        {
                            throw new Exception("Read PLC Error" + StartAddress + "." + BitIndex);
                        }
                        for (int i = 0; i < length; i++)
                        {
                            v[i] += ((int)ByteValue[2 * i]) << 8;
                            v[i] += ByteValue[2 * i + 1];
                        }
                        return v;
                    }
                }
            }
            else
            {
                throw new Exception("Wrong PLC Read Address" + StartAddress.ToString() + "." + BitIndex.ToString());
            }
        }
        //public void Read(PLC_Cell cell)
        //{
        //    string regType = string.Empty;
        //    switch (cell.Type)
        //    {
        //        case PLC_IO_Flag.CIO:
        //            regType = "CIO";
        //            break;
        //        case PLC_IO_Flag.DM:
        //            regType = "D";
        //            break;
        //        case PLC_IO_Flag.H:
        //            regType = "H";
        //            break;
        //        case PLC_IO_Flag.E:
        //            regType = "E";
        //            break;
        //        default:
        //            break;
        //    }
        //    if (!base.ReadPacket(regType, cell.Start_Addr, cell.DataValue))
        //    {
        //        throw new Exception("Read PLC Error" + cell.Start_Addr.ToString() + "." + cell.Bit_Address.ToString());
        //    }
        //    if (cell.IntValue == null)
        //    {
        //        cell.IntValue = new int[cell.Data_Len];
        //    }
        //    for (int i = 0; i < cell.Data_Len; i++)
        //    {
        //        cell.IntValue[i] = 0;
        //        cell.IntValue[i] += ((int)cell.DataValue[2 * i]) << 8;
        //        cell.IntValue[i] += cell.DataValue[2 * i + 1];
        //    }
        //    cell.BoolValue = this.GetBitValue(cell.IntValue[0], cell.Bit_Address);
        //}

        private bool GetBitValue(int value, int addr)
        {
            addr = 1 << addr;
            if ((value & addr) > 0)
            {
                return true;
            }
            //if (((value & (1 << (addr & 0x1f))) >> addr) != 1)
            //{
            //    return false;
            //}
            return false;
        }
    }
}
